﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using Jinjia.Approve.Entity;
using Jinjia.Approve.Entity.Entity;
using Jinjia.Approve.Entity.Entity.JJFlow;
using Jinjia.Approve.IRepository.JJFlow;
using Jinjia.Approve.Model.Input.JJFlow;
using Jinjia.Approve.Model.VM.JJFlow;
using Jinjia.Core.BaseInfrastructure.StorageModel.Model;
using Jinjia.Core.UnitOfWork.UnitOfWorkComponent;
using SqlSugar;

namespace Jinjia.Approve.Repository.JJFlow
{
    public class FlowInstanceRepository : IFlowInstanceRepository
    {
        private readonly ISqlSugarClient _db;

        public FlowInstanceRepository(IUnitOfWork unitOfWork)
        {
            _db = unitOfWork.GetDbClient();
        }

        public async Task<List<jj_flow_instance>> IsExist(string modular_key, int template_id, string biz_order_id)
        {
            var list = await _db.Queryable<jj_flow_instance>().Where(x => x.biz_order_id == biz_order_id && x.modular_key == modular_key && (x.status == "0" || x.status == "20"))
                .ToListAsync();
            return list;
        }

        public async Task<jj_flow_instance> GetInstanceInfo(string modular_key, string biz_order_id)
        {
            var model = await _db.Queryable<jj_flow_instance>()
                .Where(x => x.biz_order_id == biz_order_id && x.modular_key == modular_key && x.status != "30")
                .OrderBy(x => x.id, OrderByType.Desc)
                .FirstAsync();
            return model;
        }

        public async Task<List<jj_flow_instance>> GetListAsync(Expression<Func<jj_flow_instance, bool>> expression)
        {
            return await _db.Queryable<jj_flow_instance>().Where(expression).ToListAsync();
        }

        public async Task<int> Save(jj_flow_instance data)
        {
            if (data.id <= 0) //新增
            {
                var id = await _db.Insertable(data).ExecuteReturnIdentityAsync();
                return id;
            }
            else
            {
                await _db.Updateable(data)
                    .Where(x => x.id == data.id)
                    .ExecuteCommandAsync();
                return data.id;
            }
        }

        public async Task<jj_flow_instance> GetById(int id)
        {
            var instance = await _db.Queryable<jj_flow_instance>()
                .Where(x => x.id == id)
                .FirstAsync();
            return instance;
        }

        public async Task<List<jj_flow_instance>> GetByModularKeyAndInstanceIds(string modular_key, List<int> instanceIds, string status = "0")
        {
            var jjFlowInstances = await _db.Queryable<jj_flow_instance>()
                .Where(a => a.status == status && a.modular_key == modular_key)
                .In(a => a.id, instanceIds)
                .ToListAsync();
            return jjFlowInstances;
        }

        public async Task<List<jj_flow_instance>> GetInstanceList(string modular_key, string biz_order_id)
        {
            var list = await _db.Queryable<jj_flow_instance>()
                .Where(x => x.biz_order_id == biz_order_id && x.modular_key == modular_key)
                .OrderBy(x => x.id, OrderByType.Desc).ToListAsync();
            return list;
        }

        public async Task<List<string>> GetUserProcessedBizOrderId(string system_key, string big_modular_key, string modular_key, int user_id)
        {
            var instance_ids = new List<string>();
            var modularKeys = modular_key.Split(',');
            var sqlWhere = new StringBuilder(" deleted=0 ");
            if (!string.IsNullOrWhiteSpace(system_key))
            {
                sqlWhere.Append($" and system_key ='{system_key}'");
            }

            if (!string.IsNullOrWhiteSpace(big_modular_key))
            {
                sqlWhere.Append($" and big_modular_key ='{big_modular_key}'");
            }

            if (!string.IsNullOrWhiteSpace(modular_key))
            {
                sqlWhere.Append($" and modular_key in ('{string.Join("','", modularKeys)}')");
            }

            //获取到模板列表
            var template_id = await _db.Queryable<jj_flow_mapping_tbl>().Where(sqlWhere.ToString()).Select(a => a.template_id).FirstAsync();
            if (template_id == 0)
            {
                return instance_ids;
            }

            //通过 拒绝的 列表
            var instance_infos = await _db.Queryable<jj_flow_track>()
                .Where(x => x.create_user_id == user_id && x.operation_result != 99)
                .Select(x => x.instance_id)
                .ToListAsync();

            if (instance_infos == null || instance_infos.Count == 0)
            {
                return instance_ids;
            }

            instance_ids = (await _db.Queryable<jj_flow_instance>().Where(a => modularKeys.Contains(a.modular_key))
                    .In(a => a.id, instance_infos)
                    .Select(a => a.biz_order_id)
                    .ToListAsync())
                .Distinct()
                .ToList();
            return instance_ids;
        }

        public async Task<List<string>> GetUserCreateApplyBizOrderId(string system_key, string big_modular_key, string modular_key, int user_id)
        {
            var instance_ids = new List<string>();
            var modularKeys = modular_key.Split(',');
            var sqlWhere = new StringBuilder(" deleted=0 ");
            if (!string.IsNullOrWhiteSpace(system_key))
            {
                sqlWhere.Append($" and system_key ='{system_key}'");
            }

            if (!string.IsNullOrWhiteSpace(big_modular_key))
            {
                sqlWhere.Append($" and big_modular_key ='{big_modular_key}'");
            }

            if (!string.IsNullOrWhiteSpace(modular_key))
            {
                sqlWhere.Append($" and modular_key in ('{string.Join("','", modularKeys)}')");
            }

            //获取到模板列表
            var template_id = await _db.Queryable<jj_flow_mapping_tbl>()
                .Where(sqlWhere.ToString())
                .Select(a => a.template_id).FirstAsync();

            if (template_id == 0)
            {
                return instance_ids;
            }

            // 发起 列表
            var instance_infos = await _db.Queryable<jj_flow_track>()
                .Where(x => x.create_user_id == user_id && x.operation_result == 99).Select(x => x.instance_id)
                .ToListAsync();

            if (instance_infos == null || instance_infos.Count == 0)
            {
                return instance_ids;
            }

            instance_ids = (await _db.Queryable<jj_flow_instance>().Where(a => modularKeys.Contains(a.modular_key))
                    .In(a => a.id, instance_infos)
                    .Select(a => a.biz_order_id)
                    .ToListAsync())
                .Distinct()
                .ToList();
            return instance_ids;
        }

        public async Task<PageListSearchResultVM<JJInstanceViewModel>> GetInstancePageList(JJInstanceSearchCondition searchCondition, int user_id)
        {
            var queryable = _db.Queryable<jj_flow_instance, jj_flow_template, jj_flow_mapping_tbl, erpa_user_tbl, erpa_user_tbl, erpa_base_tbl, jj_node_reference, jj_node_reference, jj_flow_instance_emp, erpa_user_tbl>(
                (a, b, c, d, e, f, h, j, k, l) => new JoinQueryInfos(
                    JoinType.Left, a.template_id == b.id,
                    JoinType.Left, c.template_id == a.template_id,
                    JoinType.Left, a.create_user_id == d.id,
                    JoinType.Left, a.update_user_id == e.id,
                    JoinType.Left, a.status == f.value && f.code_type == "jj_flow_instance_status",
                    JoinType.Left, h.flow_instance_id == a.id && a.current_node_id == h.node_id,
                    JoinType.Left, j.flow_instance_id == a.id && h.sequence == (j.sequence - 1),
                    JoinType.Left, k.instance_id == a.id && k.node_id == j.node_id && k.is_complete == 0,
                    JoinType.Left, l.id == k.user_id && a.status == "0"
                ));

            if (!string.IsNullOrEmpty(searchCondition.current_user_name))
            {
                queryable.Where($" l.user_name like '%{searchCondition.current_user_name}%' ");
            }

            if (searchCondition.template_id > 0)
            {
                queryable.Where(" b.id = @template_id ", new { template_id = searchCondition.template_id });
            }

            if (!string.IsNullOrWhiteSpace(searchCondition.biz_order_id))
            {
                queryable.Where(a => a.biz_order_id == searchCondition.biz_order_id);
            }

            if (!string.IsNullOrWhiteSpace(searchCondition.template_name))
            {
                queryable.Where(" b.template_name LIKE '%" + searchCondition.template_name + "%' ");
            }

            if (!string.IsNullOrWhiteSpace(searchCondition.create_user_name))
            {
                queryable.Where(" d.user_name LIKE '%" + searchCondition.create_user_name + "%' ");
            }

            if (!string.IsNullOrWhiteSpace(searchCondition.modular_key))
            {
                queryable.Where(" c.modular_key = @modular_key ", new { modular_key = searchCondition.modular_key });
            }

            var orderby = " a.create_time desc";
            queryable.OrderBy(!string.IsNullOrWhiteSpace(searchCondition.order_by) ? searchCondition.order_by + " " + searchCondition.direction : orderby);


            var newQuery = queryable.Select<JJInstanceViewModel>(@" a.id,a.biz_order_id,a.status,a.create_user_id,a.create_time,a.update_user_id,a.update_time,a.template_id,
             c.modular_key,c.modular_name,
             b.template_name,
             f.name as status_name,
             k.id as instance_emp_id,
             k.node_id,
             k.user_id,
             a.current_node_id,
             l.user_name as current_user_name,
             d.user_name as create_user_name,e.user_name as update_user_name ");

            var result = await newQuery.ToPageListAsync(searchCondition, new DynamicTableHeaderInput()
            {
                MethodName = "ERPAssistant.Api.Controllers.JJFlowController.GetInstancePageList",
                UserId = user_id
            });

            return result;
        }
    }
}